package club.ruanx.search.service.impl;

import club.ruanx.bean.PageBean;
import club.ruanx.search.service.SolrMovieService;
import club.ruanx.solr.entity.SolrMovie;
import club.ruanx.solr.param.SolrMovieParam;
import club.ruanx.solr.repository.SolrMovieRepository;
import club.ruanx.util.BeanUtils;
import club.ruanx.util.PinYinUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.FieldAnalysisRequest;
import org.apache.solr.client.solrj.response.AnalysisResponseBase;
import org.apache.solr.client.solrj.response.FieldAnalysisResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 阮胜
 * @date 2018/11/23 14:35
 */
@Service
@Slf4j
public class SolrMovieServiceImpl implements SolrMovieService {
    private static final String ANALYSIS_FIELD = "/analysis/field";
    private static final String FIELD_TYPE_TEXT_IK = "text_ik";
    private static final String COLLECTION_NAME_MOVIE = "movie";
    private final SolrMovieRepository solrMovieRepository;
    private final SolrTemplate solrTemplate;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    public SolrMovieServiceImpl(SolrMovieRepository solrMovieRepository, SolrTemplate solrTemplate) {
        this.solrMovieRepository = solrMovieRepository;
        this.solrTemplate = solrTemplate;
    }

    @Override
    public Page<SolrMovie> findByNameLike(String name, PageBean pageBean) {
        return solrMovieRepository.findByNameLike(name, pageBean.toPageable());
    }

    @Override
    public Page<SolrMovie> searchMovieWithDistance(String keywords, int distance, PageBean pageBean) {
        return solrMovieRepository.findByKeywordsWithDistance(keywords, distance, pageBean.toPageable());
    }

    @Override
    public Page<SolrMovie> searchMovie(String keywords, PageBean pageBean) {
        return solrMovieRepository.findByKeywords(keywords, pageBean.toPageable());
    }

    @Override
    public void save(SolrMovieParam solrMovieParam) {
        SolrMovie solrMovie = new SolrMovie();
        BeanUtils.copyPropertiesIgnoreNull(solrMovieParam, solrMovie);
        try {
            String pinYin = PinYinUtil.getPinYin(solrMovieParam.getName());
            String shortPinyin = PinYinUtil.getFirstSpell(solrMovieParam.getName());
            solrMovie.setPinyin(pinYin);
            solrMovie.setShortPinyin(shortPinyin);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        solrMovieRepository.save(solrMovie);
    }

    @Override
    public void syncMovie(String... movieIds) {
    }

    @Override
    public Set<String> analyzeField(String field) throws IOException, SolrServerException {
        FieldAnalysisRequest request = new FieldAnalysisRequest(ANALYSIS_FIELD);
        request.addFieldType(FIELD_TYPE_TEXT_IK);
        request.setFieldValue(field);
        FieldAnalysisResponse response = request.process(solrTemplate.getSolrClient(), COLLECTION_NAME_MOVIE);
        HashSet<String> keySet = new HashSet<>();
        for (Map.Entry<String, FieldAnalysisResponse.Analysis> allFieldTypeAnalysis : response.getAllFieldTypeAnalysis()) {
            for (AnalysisResponseBase.AnalysisPhase indexPhase : allFieldTypeAnalysis.getValue().getIndexPhases()) {
                List<String> key = indexPhase.getTokens().stream()
                        .map(AnalysisResponseBase.TokenInfo::getText)
                        .collect(Collectors.toList());
                keySet.addAll(key);
            }
        }
        return keySet;
    }

    @Override
    public Page<SolrMovie> searchMovieWithNullDistance(String keywords, PageBean pageBean) {
        return solrMovieRepository.findByKeywordsWithNullDistance(keywords, pageBean.toPageable());
    }

    @Override
    public boolean delete(String movieId) {
        solrMovieRepository.deleteById(movieId);
        return true;
    }
}
